import {
  Injectable,
  BadRequestException,
  NotFoundException,
} from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import {
  CreateShareLinkDto,
  ShareLinkResponseDto,
  ClickShareLinkDto,
  ClickShareLinkResponseDto,
  ShareStatsResponseDto,
  ShareHistoryResponseDto,
} from './dto/share.dto';
import * as crypto from 'crypto';

@Injectable()
export class ShareService {
  constructor(private readonly prisma: PrismaService) {}

  // 分享奖励配置
  private readonly shareRewardConfig = {
    SHARER_REWARD: 10, // 分享者奖励积分
    CLICKER_REWARD: 5, // 点击者奖励积分
    NEW_USER_BONUS: 20, // 新用户额外奖励
  };

  /**
   * 生成分享token
   */
  private generateShareToken(): string {
    return 'share_' + crypto.randomBytes(16).toString('hex');
  }

  /**
   * 创建分享链接
   */
  async createShareLink(
    userId: number,
    createDto: CreateShareLinkDto,
  ): Promise<ShareLinkResponseDto> {
    // 验证用户是否存在
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
      select: { id: true, nickname: true },
    });

    if (!user) {
      throw new BadRequestException('用户不存在');
    }

    // 验证目标ID（如果是短剧或章节分享）
    if (createDto.shareType === 'SHORT' && createDto.targetId) {
      const shorts = await this.prisma.short.findUnique({
        where: { id: createDto.targetId },
      });
      if (!shorts) {
        throw new BadRequestException('短剧不存在');
      }
    } else if (createDto.shareType === 'CHAPTER' && createDto.targetId) {
      const chapter = await this.prisma.shortsChapter.findUnique({
        where: { id: createDto.targetId },
      });
      if (!chapter) {
        throw new BadRequestException('章节不存在');
      }
    }

    // 生成过期时间
    let expiresAt: Date | null = null;
    if (createDto.expireDays && createDto.expireDays > 0) {
      expiresAt = new Date();
      expiresAt.setDate(expiresAt.getDate() + createDto.expireDays);
    }

    // 使用事务创建分享链接并更新短剧分享计数
    const result = await this.prisma.$transaction(async (prisma) => {
      // 创建分享链接
      const shareToken = this.generateShareToken();
      const shareLink = await prisma.shareLink.create({
        data: {
          shareToken,
          userId,
          shareType: createDto.shareType,
          targetId: createDto.targetId,
          expiresAt,
        },
      });
      console.log(createDto, 'createDto');

      // 如果是短剧分享，更新短剧的分享计数
      if (createDto.shareType === 'SHORT' && createDto.targetId) {
        await prisma.short.update({
          where: { id: createDto.targetId },
          data: { shareCount: { increment: 1 } },
        });
      }

      return shareLink;
    });

    // 构建分享URL
    const baseUrl =
      process.env.NODE_ENV === 'production'
        ? process.env.BASE_URL
        : 'http://192.168.1.4:3000';
    const shareUrl = `${baseUrl}/api/share?token=${result.shareToken}`;

    return {
      id: result.id,
      shareToken: result.shareToken,
      shareUrl,
      shareType: result.shareType,
      targetId: result.targetId || undefined, // 将null转换为undefined22
      isActive: result.isActive,
      expiresAt: result.expiresAt || undefined, // 将null转换为undefined
      createdAt: result.createdAt,
    };
  }

  /**
   * 点击分享链接
   */
  async clickShareLink(
    clickDto: ClickShareLinkDto,
    clickerUserId?: number,
  ): Promise<ClickShareLinkResponseDto> {
    // 查找分享链接
    const shareLink = await this.prisma.shareLink.findUnique({
      where: { shareToken: clickDto.shareToken },
      include: {
        user: {
          select: { id: true, nickname: true },
        },
      },
    });

    if (!shareLink) {
      throw new NotFoundException('分享链接不存在');
    }

    // 检查链接是否激活
    if (!shareLink.isActive) {
      throw new BadRequestException('分享链接已失效');
    }

    // 检查链接是否过期
    if (shareLink.expiresAt && shareLink.expiresAt < new Date()) {
      throw new BadRequestException('分享链接已过期');
    }

    // 检查是否是分享者自己点击
    // if (clickerUserId === shareLink.userId) {
    //   return {
    //     success: false,
    //     message: '不能点击自己的分享链接',
    //     isNewUser: false,
    //     sharerRewardPoints: 0,
    //     clickerRewardPoints: 0
    //   };
    // }

    // 检查是否已经点击过（防止重复奖励）
    const existingClick = await this.prisma.shareClickRecord.findFirst({
      where: {
        shareLinkId: shareLink.id,
        OR: [
          { clickerUserId: clickerUserId },
          { ipAddress: clickDto.ipAddress },
        ],
      },
    });

    let isNewUser = false;
    let clickRecord: any;

    if (existingClick) {
      // 已经点击过，不发放奖励
      return {
        success: true,
        message: '链接已访问过',
        isNewUser: false,
        sharerRewardPoints: 0,
        clickerRewardPoints: 0,
        shareLink: {
          id: shareLink.id,
          shareType: shareLink.shareType,
          targetId: shareLink.targetId || undefined, // 将null转换为undefined
          sharer: {
            id: shareLink.user.id,
            nickname: shareLink.user.nickname,
          },
        },
      };
    }

    // 检查是否是新用户
    if (clickerUserId) {
      const user = await this.prisma.user.findUnique({
        where: { id: clickerUserId },
        select: { createdAt: true },
      });

      if (user) {
        // 如果用户是今天注册的，认为是新用户
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        isNewUser = user.createdAt >= today;
      }
    } else {
      // 未登录用户暂时不算新用户
      isNewUser = false;
    }

    // 创建点击记录
    clickRecord = await this.prisma.shareClickRecord.create({
      data: {
        shareLinkId: shareLink.id,
        clickerUserId,
        ipAddress: clickDto.ipAddress,
        userAgent: clickDto.userAgent,
        isNewUser,
        isRewardGiven: true,
      },
    });

    // 计算奖励积分
    const sharerRewardPoints =
      this.shareRewardConfig.SHARER_REWARD +
      (isNewUser ? this.shareRewardConfig.NEW_USER_BONUS : 0);
    const clickerRewardPoints = clickerUserId
      ? this.shareRewardConfig.CLICKER_REWARD
      : 0;

    // 发放奖励
    await this.prisma.$transaction(async (prisma) => {
      // 给分享者发放奖励
      if (sharerRewardPoints > 0) {
        await prisma.user.update({
          where: { id: shareLink.userId },
          data: { points: { increment: sharerRewardPoints } },
        });

        await prisma.shareReward.create({
          data: {
            shareLinkId: shareLink.id,
            clickRecordId: clickRecord.id,
            userId: shareLink.userId,
            rewardType: 'SHARE_REWARD',
            points: sharerRewardPoints,
            reason: isNewUser ? '分享链接被新用户点击' : '分享链接被点击',
          },
        });
      }

      // 给点击者发放奖励
      if (clickerUserId && clickerRewardPoints > 0) {
        await prisma.user.update({
          where: { id: clickerUserId },
          data: { points: { increment: clickerRewardPoints } },
        });

        await prisma.shareReward.create({
          data: {
            shareLinkId: shareLink.id,
            clickRecordId: clickRecord.id,
            userId: clickerUserId,
            rewardType: 'CLICK_REWARD',
            points: clickerRewardPoints,
            reason: '点击分享链接',
          },
        });
      }
    });

    return {
      success: true,
      message: '分享链接访问成功',
      isNewUser,
      sharerRewardPoints,
      clickerRewardPoints,
      shareLink: {
        id: shareLink.id,
        shareType: shareLink.shareType,
        targetId: shareLink.targetId || undefined, // 将null转换为undefined
        sharer: {
          id: shareLink.user.id,
          nickname: shareLink.user.nickname,
        },
      },
    };
  }

  /**
   * 获取用户分享统计
   */
  async getUserShareStats(userId: number): Promise<ShareStatsResponseDto> {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);

    // 获取总分享次数
    const totalShares = await this.prisma.shareLink.count({
      where: { userId },
    });

    // 获取总点击次数
    const totalClicks = await this.prisma.shareClickRecord.count({
      where: {
        shareLink: { userId },
      },
    });

    // 获取新用户数量
    const newUsersCount = await this.prisma.shareClickRecord.count({
      where: {
        shareLink: { userId },
        isNewUser: true,
      },
    });

    // 获取总奖励积分
    const totalRewardResult = await this.prisma.shareReward.aggregate({
      where: { userId },
      _sum: { points: true },
    });
    const totalRewardPoints = totalRewardResult._sum.points || 0;

    // 获取今日分享次数
    const todayShares = await this.prisma.shareLink.count({
      where: {
        userId,
        createdAt: {
          gte: today,
          lt: tomorrow,
        },
      },
    });

    // 获取今日点击次数
    const todayClicks = await this.prisma.shareClickRecord.count({
      where: {
        shareLink: { userId },
        createdAt: {
          gte: today,
          lt: tomorrow,
        },
      },
    });

    // 获取今日奖励积分
    const todayRewardResult = await this.prisma.shareReward.aggregate({
      where: {
        userId,
        createdAt: {
          gte: today,
          lt: tomorrow,
        },
      },
      _sum: { points: true },
    });
    const todayRewardPoints = todayRewardResult._sum.points || 0;

    return {
      totalShares,
      totalClicks,
      newUsersCount,
      totalRewardPoints,
      todayShares,
      todayClicks,
      todayRewardPoints,
    };
  }

  /**
   * 获取用户分享历史
   */
  async getUserShareHistory(
    userId: number,
    page: number = 1,
    pageSize: number = 10,
  ): Promise<ShareHistoryResponseDto> {
    const skip = (page - 1) * pageSize;

    const [shareLinks, total] = await Promise.all([
      this.prisma.shareLink.findMany({
        where: { userId },
        include: {
          clickRecords: {
            select: { id: true },
          },
          rewards: {
            select: { points: true },
          },
        },
        orderBy: { createdAt: 'desc' },
        skip,
        take: pageSize,
      }),
      this.prisma.shareLink.count({
        where: { userId },
      }),
    ]);

    const formattedLinks = shareLinks.map((link) => ({
      id: link.id,
      shareToken: link.shareToken,
      shareType: link.shareType,
      targetId: link.targetId || undefined, // 将null转换为undefined
      clickCount: link.clickRecords.length,
      rewardPoints: link.rewards.reduce(
        (sum, reward) => sum + reward.points,
        0,
      ),
      isActive: link.isActive,
      expiresAt: link.expiresAt || undefined, // 将null转换为undefined
      createdAt: link.createdAt,
    }));

    return {
      shareLinks: formattedLinks,
      total,
      page,
      pageSize,
    };
  }

  /**
   * 根据token获取分享链接信息
   */
  async getShareLinkByToken(shareToken: string) {
    return this.prisma.shareLink.findUnique({
      where: { shareToken },
      include: {
        user: {
          select: { id: true, nickname: true },
        },
      },
    });
  }

  /**
   * 禁用分享链接
   */
  async deactivateShareLink(userId: number, shareLinkId: number) {
    const shareLink = await this.prisma.shareLink.findFirst({
      where: {
        id: shareLinkId,
        userId,
      },
    });

    if (!shareLink) {
      throw new NotFoundException('分享链接不存在');
    }

    return this.prisma.shareLink.update({
      where: { id: shareLinkId },
      data: { isActive: false },
    });
  }

  /**
   * 根据分享类型和目标ID获取内容信息
   */
  async getContentInfo(shareType: string, targetId: number): Promise<any> {
    if (shareType === 'SHORT' && targetId) {
      // 获取短剧信息
      const shorts = await this.prisma.short.findUnique({
        where: { id: targetId },
        select: {
          id: true,
          title: true,
          coverUrl: true,
          summary: true,
          instructor: true,
        },
      });
      return shorts;
    } else if (shareType === 'CHAPTER' && targetId) {
      // 获取章节信息，包含短剧信息
      const chapter = await this.prisma.shortsChapter.findUnique({
        where: { id: targetId },
        select: {
          id: true,
          title: true,
          shorts: {
            select: {
              id: true,
              title: true,
              coverUrl: true,
              summary: true,
              instructor: true,
            },
          },
        },
      });
      return chapter;
    }
    return null;
  }
}
